﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Media.Animation;
using NUnit.Framework;
using Rhino.Mocks;

namespace Present.Commands.Tests
{

    public abstract class PresentVisualStateManagerTestCaseBase : TestCase
    {
        private Button button;
        const string StateName = "NewState";


        public override void Setup()
        {
            base.Setup();
            button = CreateButtonWithVisualState(StateName);
        }

        protected abstract Button CreateButtonWithVisualState(string newstate);

        [Test]
        public void ShouldChangeState()
        {
            Assert.IsTrue(PresentVisualStateManager.ChangeState(button, StateName, () => { }));
        }

        [Test]
        public void ShouldFindState()
        {
            Assert.IsNotNull(PresentVisualStateManager.TryGetState(StateName, button));
        }

        [Test,Ignore("Can't get Storyboard Completed to fire inside a test")]
        public void ShouldExecuteCompletionCodeAfterAnimationsFinish()
        {
            var state = PresentVisualStateManager.TryGetState(StateName, button);

            state.Storyboard = new Storyboard();
            var a = new DoubleAnimation(0, 1, new Duration(TimeSpan.FromMilliseconds(200)));
            state.Storyboard.Children.Add(a);
            state.Storyboard.Duration = TimeSpan.FromMilliseconds(200);

            Storyboard.SetTargetProperty(a, new PropertyPath("Height"));
            Storyboard.SetTarget(state.Storyboard, button);
            Storyboard.SetTarget(a, button);
            

            var signal = new ManualResetEvent(false);
            PresentVisualStateManager.ChangeState(button, state.Name, () => signal.Set());
            Assert.IsTrue(signal.WaitOne(1000), "Oncomplete never called");

        }
    }

    [TestFixture, RequiresSTA]
    public class PresentVisualStateManagerTestCase_StatesInline : PresentVisualStateManagerTestCaseBase
    {
        protected override Button CreateButtonWithVisualState(string newstate)
        {
            var button = new Button();
            var groups = VisualStateManager.GetVisualStateGroups(button);
            var group = new VisualStateGroup();
            group.States.Add(new VisualState { Name = newstate });
            groups.Add(group);
            return button;
        }
    }

    [TestFixture, RequiresSTA]
    public class PresentVisualStateManagerTestCase_StatesInControlTemplate : PresentVisualStateManagerTestCaseBase
    {
        protected override Button CreateButtonWithVisualState(string newstate)
        {
            var button = new Button { Template = CreateButtonTemplateWithVisualState(newstate) };
            button.ApplyTemplate();
            return button;
        }

      
        private ControlTemplate CreateButtonTemplateWithVisualState(String state)
        {
            const string templateXamlDefinition =
            @"<ControlTemplate TargetType='{{x:Type Button}}'>
              <Grid>
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name=""Main"">
                       <VisualState x:Name=""{0}"">
                            <Storyboard />
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
              </Grid>
            </ControlTemplate>";


            var xamlStream = new MemoryStream(Encoding.ASCII.GetBytes(string.Format(templateXamlDefinition, state)));

            var pc = new ParserContext();
            pc.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
            pc.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");

            return (ControlTemplate)XamlReader.Load(xamlStream, pc);
        }
    }
}
